package com.globefrog.example.provider.config;

import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.support.http.StatViewServlet;
import com.alibaba.druid.support.http.WebStatFilter;
import com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean;
import java.sql.SQLException;
import javax.sql.DataSource;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.session.SqlSessionFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;

/**
 * @author : Globe-Frog
 * @date : Create in 2021/7/7
 */
@Slf4j
@Configuration
public class DruidDatasourceConfig {

  @Value("${spring.datasource.druid.url}")
  private String connectionUrl;
  @Value("${spring.datasource.druid.username}")
  private String username;
  @Value("${spring.datasource.druid.password}")
  private String password;
  @Value("${spring.datasource.druid.initialSize}")
  private Integer initialSize;
  @Value("${spring.datasource.druid.minIdle}")
  private Integer minIdle;
  @Value("${spring.datasource.druid.maxActive}")
  private Integer maxActive;
  @Value("${spring.datasource.druid.maxWait}")
  private Integer maxWait;
  @Value("${spring.datasource.druid.timeBetweenEvictionRunsMillis}")
  private Integer timeBetweenEvictionRunsMillis;
  @Value("${spring.datasource.druid.minEvictableIdleTimeMillis}")
  private Integer minEvictableIdleTimeMillis;
  @Value("${spring.datasource.druid.validationQuery}")
  private String validationQuery;
  @Value("${spring.datasource.druid.testWhileIdle}")
  private Boolean testWhileIdle;
  @Value("${spring.datasource.druid.testOnBorrow}")
  private Boolean testOnBorrow;
  @Value("${spring.datasource.druid.testOnReturn}")
  private Boolean testOnReturn;
  @Value("${spring.datasource.druid.poolPreparedStatements}")
  private Boolean poolPreparedStatements;
  @Value("${spring.datasource.druid.maxPoolPreparedStatementPerConnectionSize}")
  private Integer maxPoolPreparedStatementPerConnectionSize;


  //    配置数据源
  @Bean(name = "basisDataSource", initMethod = "init", destroyMethod = "close")
  public DataSource dataSource() {
    log.info("初始化DruidDataSource");
    DruidDataSource dds = new DruidDataSource();
    dds.setDriverClassName("com.mysql.jdbc.Driver");
    dds.setUrl(connectionUrl);
    dds.setUsername(username);
    dds.setPassword(password);
    dds.setInitialSize(initialSize);
    dds.setMinIdle(minIdle);
    dds.setMaxActive(maxActive);
    dds.setMaxWait(maxWait);
    dds.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis);
    dds.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);
    dds.setValidationQuery(validationQuery);
    dds.setTestWhileIdle(testWhileIdle);
    dds.setTestOnBorrow(testOnBorrow);
    dds.setTestOnReturn(testOnReturn);
    dds.setPoolPreparedStatements(poolPreparedStatements);
    dds.setMaxPoolPreparedStatementPerConnectionSize(maxPoolPreparedStatementPerConnectionSize);
    return dds;
  }

  @Bean
  public ServletRegistrationBean druidServlet() {
    return new ServletRegistrationBean(new StatViewServlet(), "/druid/*");
  }

  @Bean
  public FilterRegistrationBean filterRegistrationBean() {
    FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
    filterRegistrationBean.setFilter(new WebStatFilter());
    filterRegistrationBean.addUrlPatterns("/*");
    filterRegistrationBean
        .addInitParameter("exclusions", "*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*");
    return filterRegistrationBean;
  }

  @Bean("sqlSessionFactory")
  @Primary
  public SqlSessionFactory sqlSessionFactory() throws Exception {
    MybatisSqlSessionFactoryBean sqlSessionFactoryBean = new MybatisSqlSessionFactoryBean();
    sqlSessionFactoryBean.setDataSource(dataSource());
    return sqlSessionFactoryBean.getObject();
  }

  @Bean
  public PlatformTransactionManager transactionManager() throws SQLException {
    return new DataSourceTransactionManager(dataSource());
  }
}
